package org.lhl.readruler.connection

import android.bluetooth.*
import com.blankj.utilcode.util.LogUtils
import io.reactivex.processors.FlowableProcessor
import lhl.kotlinextends.e
import org.lhl.readruler.mApp
import org.lhl.readruler.utils.DataTool
import java.util.*
import java.util.concurrent.LinkedBlockingQueue

/**
 * 蓝牙4.x连接
 */
class BleBluetoothConnection(publish: FlowableProcessor<Any>, parser: Parser) : AbstractConnect(publish, parser) {

    val CLIENT_CHARACTERISTIC_CONFIG_DESCRIPTOR_UUID = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb")
    val UUID_HEART_RATE_MEASUREMENT = UUID.fromString("00002a37-0000-1000-8000-00805f9b34fb")
    private var mBluetoothGatt: BluetoothGatt? = null
    private var characteristic: BluetoothGattCharacteristic? = null
    private var mPacketsToRead = LinkedBlockingQueue<ByteArray>()
    private var device: BluetoothDevice? = null

    fun connectDevice(device: BluetoothDevice) {
        this.device = device
        connect()
    }

    override fun openConnection() {
        mBluetoothGatt = device?.connectGatt(mApp, false, mGattCallback)
    }

    override fun closeConnection() {
        mBluetoothGatt?.disconnect()
        mBluetoothGatt?.close()
        mBluetoothGatt = null
    }

    override fun sendBuffer(byteArray: ByteArray) {
        if (characteristic == null || mBluetoothGatt == null) return
        val sliceCount = byteArray.size.let { it / 20 + if (it % 20 > 0) 1 else 0 }
        for (i in 0 until sliceCount) {
            val space = if (i == sliceCount - 1) byteArray.size else (i * 20 + 20)
            characteristic?.value = byteArray.sliceArray((i * 20) until space)
            DataTool.bytesToHexString(characteristic?.value).e()
            LogUtils.e("发送长度 = " + characteristic?.value?.size)
            mBluetoothGatt?.writeCharacteristic(characteristic)
            Thread.sleep(10)
        }
    }

    override fun readDataBlock(byteArray: ByteArray): Int {
        val read = mPacketsToRead.take()
        for (i in read.indices) {
            byteArray[i] = read[i]
        }
        return read.size
    }


    private val mGattCallback = object : BluetoothGattCallback() {

        override fun onConnectionStateChange(gatt: BluetoothGatt, status: Int, newState: Int) {
            "蓝牙测试   onConnectionStateChange  status = $status  newState = $newState ".e()

            if (newState == BluetoothProfile.STATE_CONNECTED) { //连接成功
                LogUtils.e("连接1")
                gatt.discoverServices()
            } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {  //连接失败
                LogUtils.e("连接失败")
                disConnect()
            }
        }

        override fun onServicesDiscovered(gatt: BluetoothGatt, status: Int) {
            super.onServicesDiscovered(gatt, status)

            "蓝牙测试   onServicesDiscovered  status = $status ".e()

            if (status == BluetoothGatt.GATT_SUCCESS) {
                LogUtils.e("发现服务")
                val services = gatt.services
                services.forEach {
                    it.characteristics.forEach {
                        val c_uuid = it.uuid.toString()
                        if (c_uuid.startsWith("00001111") || c_uuid.startsWith("0000fff6") || c_uuid.startsWith(
                                "0000ffe1"
                            )
                        ) {
                            gatt.setCharacteristicNotification(it, true)
                            characteristic = it
                            val descriptor = characteristic?.getDescriptor(
                                CLIENT_CHARACTERISTIC_CONFIG_DESCRIPTOR_UUID
                            )
                            descriptor?.value = BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE
                            mBluetoothGatt?.writeDescriptor(descriptor)
                            if (connectState == ConnectState.CONNECTING) {
                                connectState = ConnectState.CONNECTED
                                publish.onNext(AttEvent(Event.CONNECTED))
                            }
                            LogUtils.e("连接成功 uuid = $c_uuid")
                            return
                        }
                    }
                }
            } else {
                LogUtils.e("发现服务失败")
            }
        }

        override fun onCharacteristicChanged(
            gatt: BluetoothGatt?,
            characteristic: BluetoothGattCharacteristic?
        ) {
            super.onCharacteristicChanged(gatt, characteristic)
//            "蓝牙测试   onCharacteristicChanged  value = $${characteristic?.value} ".e()
            publish.onNext(AttEvent(Event.DATA_META, characteristic?.value))
            mPacketsToRead.offer(characteristic?.value)
        }
    }

}